package com.tiger.admin.http.logs;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.tiger.admin.Db;
import com.tiger.admin.dto.PaginationResult;
import com.tiger.admin.http.logs.dto.ExportDto;
import com.tiger.admin.http.logs.dto.PageDto;
import com.tiger.admin.http.logs.type.BackendLogRes;
import com.tiger.db.entity.ExportTask;
import com.tiger.db.entity.Member;
import com.tiger.mongodb.entity.BackendLog;
import com.tiger.mongodb.entity.PortalLoginLog;
import com.tiger.utils.Utils;
import org.apache.poi.ss.usermodel.*;
import org.bson.Document;
import org.bson.types.ObjectId;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

@Service
public class PortalLoginLogService {
    private final short exportSize = 5000;
    private final MongoTemplate mongoTemplate;
    private final Db db;

    public PortalLoginLogService(MongoTemplate mongoTemplate, Db db) {
        this.mongoTemplate = mongoTemplate;
        this.db = db;
    }

    public PaginationResult<PortalLoginLog> page(PageDto page) {
        long startTime = page.getStartTime();
        long endTime = page.getEndTime();

        PaginationResult<PortalLoginLog> result = new PaginationResult<>();

        Criteria criteria = new Criteria();
        Sort sort = Sort.by(Sort.Direction.DESC, "_id"); // 升序


        if(page.getKey() != null && !page.getKey().isEmpty()) {
            criteria.and("account").is(page.getKey());
        }

        if(page.getIp() != null && !page.getIp().isEmpty()) {
            criteria.and("ip").is(page.getIp());
        }

        if(startTime != 0 && endTime != 0) {
            if(startTime == endTime) {
                criteria.and("time").is(startTime);
            }else {
                criteria.and("time").gte(startTime).lt(endTime);
            }
        }


        Query query = new Query(criteria);
        query.with(sort);

        result.setTotal(mongoTemplate.count(query, PortalLoginLog.class));

        if(result.getTotal() > 0) {
            query.skip((page.getPageNo() - 1) * page.getPageSize()).limit(page.getPageSize());

            List<PortalLoginLog> rows = mongoTemplate.find(query, PortalLoginLog.class);
            for(PortalLoginLog row:rows) {
                row.setAccount(Utils.maskUserAccount(row.getAccount()));
            }

            result.setRows(rows);
        }

        return result;
    }


    @Async
    public void export(long id, ExportDto dto, String filePath) throws IOException {
        String _id = null;

        while (true) {
            List<PortalLoginLog> rows = query(dto, _id);
            writeToExcel(filePath, 0, rows);
            int size = rows.size();
            if(size >= exportSize) {
                _id = rows.get(size - 1).getId();
            }else {
                break;
            }
        }

        UpdateWrapper updateWrapper = new UpdateWrapper<ExportTask>();
        updateWrapper.eq("id", id);
        updateWrapper.set("status", 1);


        boolean r = db.exportTask.update(updateWrapper);

    }

    public List<PortalLoginLog> query(ExportDto dto, String _id) {
        Criteria criteria = new Criteria();

        if(_id != null && !_id.isEmpty()) {
            criteria.and("_id").gt(new ObjectId(_id));
        }

        if(dto.getKey() != null && !dto.getKey().isEmpty()) {
            criteria.and("account").is(dto.getKey());
        }

        if(dto.getIp() != null && !dto.getIp().isEmpty()) {
            criteria.and("ip").is(dto.getIp());
        }

        long startTime = dto.getStartTime();
        long endTime = dto.getEndTime();

        if(startTime > 0 || endTime > 0) {
            criteria.and("time");
            if(startTime == endTime) {
                criteria.is(startTime);
            }else {

                if(startTime > 0) {
                    criteria.gte(startTime);
                }

                if(endTime > 0) {
                    criteria.lt(startTime);
                }
            }
        }


        Query query = new Query(criteria);

        query.limit(exportSize);
        return mongoTemplate.find(query, PortalLoginLog.class);

    }

    /**
     * 向Excel文件的指定工作表写入多行数据。
     *
     * @param filePath    Excel文件路径
     * @param sheetIndex  工作表索引
     * @param data        要写入的数据，以二维数组的形式
     * @throws IOException 如果文件操作失败
     */
    public static void writeToExcel(String filePath, int sheetIndex, List<PortalLoginLog> data) throws IOException {
        FileInputStream fis = new FileInputStream(new File(filePath));
        Workbook workbook = WorkbookFactory.create(fis);
        Sheet sheet = workbook.getSheetAt(sheetIndex); // 获取工作表

        // 计算要写入数据的起始行号
        int startRow = sheet.getLastRowNum() + 1;

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");

        // 遍历数据列表，逐行写入
        for (int i = 0; i < data.size(); i++) {
            PortalLoginLog rowData = data.get(i);
            Row row = sheet.getRow(startRow + i); // 获取或创建行
            if (row == null) {
                row = sheet.createRow(startRow + i); // 如果行不存在，则创建新行
            }

            row.createCell(0).setCellValue(sdf.format(new Date(rowData.getTime() * 1000)));
            row.createCell(1).setCellValue(rowData.getAccount());
            row.createCell(2).setCellValue(rowData.getIp());
            row.createCell(3).setCellValue(rowData.getBrowser());
            row.createCell(4).setCellValue(rowData.getLocation());
            row.createCell(5).setCellValue(rowData.getType());
        }

        // 将更改写回文件
        FileOutputStream fos = new FileOutputStream(filePath);
        workbook.write(fos);
        fos.close();

        // 关闭资源
        workbook.close();
        fis.close();
    }


    public PortalLoginLog query(String id) {
        return mongoTemplate.findById(id, PortalLoginLog.class);
    }
}
